#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include "Detail/fields.hpp"

namespace rpc
{
    class BaseMessage
    {
    public:
        using ptr = std::shared_ptr<BaseMessage>;
        virtual ~BaseMessage(){}
        //获取和修改消息ID
        virtual void setId(const std::string &id) { _rid = id; }
        virtual std::string rid() { return _rid; }
        //获取和修改消息类型
        virtual void setMType(MType mtype) { _mtype = mtype; }
        virtual MType mtype() { return _mtype; }
        //序列化和反序列化
        virtual std::string serialize() = 0;
        virtual bool unserialize(const std::string &msg) = 0;
        //检查消息的正确性
        virtual bool check() = 0;
    private:
        MType _mtype;      //消息类型
        std::string _rid;  //消息id
    };

    class BaseBuffer
    {
    public:
        using ptr = std::shared_ptr<BaseBuffer>;
        virtual size_t readableSize() = 0;
        virtual int32_t peekInit32() = 0;
        virtual void retrieveInt32() = 0;
        virtual int32_t readInit32() = 0;
        virtual std::string retrieveAsString(size_t len) = 0;
    };

    class BaseProtocol
    {
    public:
        using ptr = std::shared_ptr<BaseProtocol>;
        virtual bool canProcessed(const BaseBuffer::ptr &buf) = 0;
        virtual bool onMessage(const BaseBuffer::ptr &buf, BaseMessage::ptr &msg) = 0;
        virtual std::string serialize(const BaseMessage::ptr &msg) = 0;
    };

    class BaseConnection
    {
    public:
        using ptr = std::shared_ptr<BaseConnection>;
        virtual void send(const BaseMessage::ptr &msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0;
    };

    using ConnectionCallback = std::function<void(const BaseConnection::ptr&)>;
    using CloseCallback = std::function<void(const BaseConnection::ptr&)>;
    using MessageCallback = std::function<void(const BaseConnection::ptr&, BaseBuffer::ptr&)>;
    class BaseServer
    {
    public:
        using ptr = std::shared_ptr<BaseServer>;
        virtual void setConnectionCallback(const ConnectionCallback& cb) { _cb_connection = cb; }
        virtual void setCloseCallback(const CloseCallback& cb) { _cb_close = cb; }
        virtual void setMessageCallback(const MessageCallback& cb) { _cb_message = cb; }
        virtual void Start() = 0;
    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };

    class BaseClient
    {
    public:
        using ptr = std::shared_ptr<BaseClient>;
        virtual void setConnectionCallback(const ConnectionCallback& cb) { _cb_connection = cb; }
        virtual void setCloseCallback(const CloseCallback& cb) { _cb_close = cb; }
        virtual void setMessageCallback(const MessageCallback& cb) { _cb_message = cb; }
        virtual void conncet() = 0;
        virtual void shutdown() = 0;
        virtual void send(const BaseMessage::ptr&) = 0;
        virtual BaseConnection::ptr conncetion() = 0;
        virtual bool connected() = 0;
    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };
}